001 /*
002 * Copyright 2005 Stephen J. McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.transit.local;
020
021 import java.io.IOException;
022 import java.io.InputStream;
023 import java.io.FileInputStream;
024 import java.io.OutputStream;
025 import java.io.FileOutputStream;
026 import java.io.File;
027 import java.net.URL;
028 import java.net.URLConnection;
029 import java.security.AccessController;
030 import java.security.PrivilegedExceptionAction;
031 import java.security.PrivilegedActionException;
032 import java.security.PrivilegedAction;
033
034 import net.dpml.transit.Transit;
035 import net.dpml.transit.Artifact;
036
037 /**
038 * The local URL protocol connection implementation.
039 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
040 * @version 1.0.1
041 */
042 public class LocalURLConnection extends URLConnection
043 {
044 private boolean m_connected;
045
046 private File m_target;
047
048 /**
049 * Creation of a new local handler.
050 * @param url the url to establish a connection with
051 * @exception NullPointerException if the url argument is null
052 */
053 LocalURLConnection( URL url )
054 throws NullPointerException
055 {
056 super( url );
057
058 m_connected = false;
059 }
060
061 /**
062 * Establish a connection.
063 *
064 * @exception IOException is an error occurs while attempting to establish
065 * the connection.
066 */
067 public void connect()
068 throws IOException
069 {
070 if( m_connected )
071 {
072 return;
073 }
074
075 m_connected = true;
076
077 try
078 {
079 AccessController.doPrivileged(
080 new PrivilegedExceptionAction()
081 {
082 public Object run()
083 throws IOException
084 {
085 String spec = url.toExternalForm();
086 try
087 {
088 Artifact artifact = Artifact.createArtifact( spec );
089 String groupSpec = artifact.getGroup();
090 String artifactName = artifact.getName();
091 String typeSpec = artifact.getType();
092 String versionSpec = artifact.getVersion();
093 File prefs = Transit.DPML_PREFS;
094 File group = new File( prefs, groupSpec );
095 File type = new File( group, typeSpec + "s" );
096 if( null == versionSpec )
097 {
098 final String filename = artifactName + "." + typeSpec;
099 m_target = new File( type, filename );
100 }
101 else
102 {
103 final String filename = artifactName + "-" + versionSpec + "." + typeSpec;
104 m_target = new File( type, filename );
105 }
106 }
107 catch( Throwable e )
108 {
109 String message = e.getMessage();
110 IOException exception = new IOException( message );
111 exception.initCause( e.getCause() );
112 throw exception;
113 }
114 return null; // nothing to return
115 }
116 }
117 );
118 }
119 catch( PrivilegedActionException e )
120 {
121 throw (IOException) e.getException();
122 }
123 }
124
125 /**
126 * Return an input stream to the resource.
127 * @return the input stream
128 * @exception IOException is an error occurs
129 */
130 public InputStream getInputStream()
131 throws IOException
132 {
133 connect();
134 if( m_target == null )
135 {
136 return null;
137 }
138 else
139 {
140 return new FileInputStream( m_target );
141 }
142 }
143
144 /**
145 * Return an output stream to the resource.
146 * @return the output stream
147 * @exception IOException if any I/O problems occur.
148 */
149 public OutputStream getOutputStream()
150 throws IOException
151 {
152 connect();
153 if( m_target == null )
154 {
155 return null;
156 }
157 else
158 {
159 if( !m_target.exists() )
160 {
161 File parent = m_target.getParentFile();
162 if( null != parent )
163 {
164 parent.mkdirs();
165 }
166 m_target.createNewFile();
167 }
168 return new FileOutputStream( m_target );
169 }
170 }
171
172 /**
173 * Return the content for this local resource.
174 * @param classes a sequence of classes against which the
175 * implementation will attempt to establish a known match
176 * @return the content object (possibly null)
177 * @exception IOException is an error occurs
178 */
179 public Object getContent( final Class[] classes )
180 throws IOException
181 {
182 connect();
183 Object result = AccessController.doPrivileged(
184 new PrivilegedAction()
185 {
186 public Object run()
187 {
188 for( int i=0; i < classes.length; i++ )
189 {
190 Class c = classes[i];
191 if( c.equals( File.class ) )
192 {
193 return m_target;
194 }
195 }
196 return null;
197 }
198 }
199 );
200
201 if( null != result )
202 {
203 return result;
204 }
205 else
206 {
207 if( null != m_target )
208 {
209 return m_target.toURL().getContent( classes );
210 }
211 else
212 {
213 return super.getContent( classes );
214 }
215 }
216 }
217 }